06|全局锁与表锁

数据库的锁是用来解决并发问题。作为用户共享的资源,当出现并发访问的时候,数据库需要合理的控制资源的访问规则,而数据库锁就是来实现这些访问规则的重要数据结构。

锁的分类

  • 全局锁
  • 表级锁
  • 行锁

全局锁

对整个数据库加锁,数据库更新语句(更删改),数据定义语句(建表,修改表结构)等操作都会被阻塞。

应用场景

全库逻辑备份(保证数据逻辑一致性)

表级锁

  • 表锁

加锁:lock tables … read/write

释放锁:手动unlock tabls,或者客户端断开的时候字段释放

影响:lock tables控制并发,锁住整张表,影响比较大。

  • 元数据锁(meta data lock,MDL)

Mysql 5.5 引入了MDL,当对一个表做增删改查的时候,加MDL读锁,当对标做结构变更操作的时候,加MDL写锁。

  • 读锁之间不互斥。
  • 读写锁与写锁之间互斥。保证表结构操作的安全性

案例

给表加字段导致系统,导致数据库挂了。

  1. session A执行读取数据操作,这时会对表加一个MDL读锁
  2. session B执行读取数据操作,这时会对表加一个MDL读锁,但是读锁之间不互斥,所以能够正常查询出数据。
  3. session C这时候给表添加字段,由于session A还没有释放MDL读锁,所以session C拿不到写锁,因此会被阻塞
  4. session D由于session C的写锁请求被阻塞,那么session D的读取请求也会被阻塞

后果: 这个表的查询语句频繁,而且客户端还有重试机制,会导致整个库的线程很快爆满。MDL锁需要等到事务提交之后再释放。

如何安全的给表加字段

  1. 查询当前执行的事务,如果有长事务在执行,则先暂停DDL,或者kill掉这个长事务。
  2. alter table设置等待时间,在指定时间内能拿到MDL写锁最好,拿不到则退出,不阻塞后面的业务语句,后面再次重试。